unit SmallStruct.BusinessObject.TSSBusinessObjectFactory;

interface

uses SmallStruct.Core,
  SmallStruct.Core.TSSObjectFactory,
  SmallStruct.BusinessObject,
  SmallStruct.Configuration;

type
  TSSBusinessObjectFactory = class(TSSObjectFactory, ISSBusinessObjectFactory)
  public
    function GetBusinessObject(const ABusinessObjectName: string): ISSBusinessObject; overload;
    function GetBusinessObject(const ABusinessObjectConfiguration: ISSConfiguration): ISSBusinessObject; overload;
  protected
    function GetBusinessObjectConfiguration(const ABusinessObjectName: string): ISSBusinessObjectConfiguration;
    procedure FreeBusinessObject(ABusinessObject: ISSBusinessObject);
  end;

implementation

uses
  SmallStruct.BusinessObject.TSSBusinessObject,
  SmallStruct.BusinessObject.TSSAdvancedBusinessObject,
  SmallStruct.Database,
  SmallStruct.BusinessObject.TSSScriptBusinessObject,
  SmallStruct.Script,
  dialogs;

{ TSSBusinessObjectFactory }

procedure TSSBusinessObjectFactory.FreeBusinessObject(ABusinessObject: ISSBusinessObject);
begin
  (ABusinessObject.GetContext as ISSBusinessObjectContext).GetBusinessObjectContainer.ReleaseObject;
  ABusinessObject.ReleaseObjectInstance;
end;

function TSSBusinessObjectFactory.GetBusinessObject(const ABusinessObjectName: string): ISSBusinessObject;
var
  BusinessObjectClass: TSSBusinessObjectClass;
  BusinessObjectContext: TSSBusinessObjectContext;
  Index: Integer;
  ObjectInstance: TSSBusinessObject;
  ReferenceBusinessObjectName: string;
  BusinessObjectConfiguration: ISSBusinessObjectConfiguration;
  ScriptLoader: ISSScriptLoader;
  Script: ISSScript;
begin
  BusinessObjectConfiguration := GetBusinessObjectConfiguration(ABusinessObjectName);

  //  Init script base Business Object Context
  if BusinessObjectConfiguration.IsBaseScript then
  begin
    ObjectInstance := TSSScriptBusinessObject.Create(nil);

    ScriptLoader := GetBusinessObject(SS_SCRIPT_LOADER) as ISSScriptLoader;

    try
      Script := ScriptLoader.LoadScript(BusinessObjectConfiguration.GetBusinessObjectName);
    finally
      FreeBusinessObject(ScriptLoader);
    end;
    BusinessObjectContext := TSSScriptBusinessObjectContext.Create(nil);

    (BusinessObjectContext as TSSScriptBusinessObjectContext).SetScript(Script);
    (BusinessObjectContext as TSSScriptBusinessObjectContext).SetDatabase(((GetSystemObject.GetGlobalObjectTable as ISSObjectContainer).GetObject(SS_DATABASE_CONNECTION_FACTORY_NAME) as ISSDatabaseConnectionFactory).GetDatabaseConnection(BusinessObjectConfiguration.GetDatabaseConnectionName));
  end
  else
    //  Init not script base Business Object Context
  begin
    BusinessObjectClass := TSSBusinessObjectClass(QueryClass(ABusinessObjectName));
    ObjectInstance := BusinessObjectClass.Create(nil);

    if BusinessObjectConfiguration.IsRequireDatabase then
    begin
      BusinessObjectContext := TSSAdvancedBusinessObjectContext.Create(nil);
      (BusinessObjectContext as TSSAdvancedBusinessObjectContext).SetDatabase(((GetSystemObject.GetGlobalObjectTable as ISSObjectContainer).GetObject(SS_DATABASE_CONNECTION_FACTORY_NAME) as ISSDatabaseConnectionFactory).GetDatabaseConnection(BusinessObjectConfiguration.GetDatabaseConnectionName));
    end
    else
      BusinessObjectContext := TSSBusinessObjectContext.Create(nil);

    //  Init Business Object references Business Object
    BusinessObjectContext.SetConfiguration(BusinessObjectConfiguration);
    for Index := 0 to (BusinessObjectContext.GetConfiguration as ISSBusinessObjectConfiguration).GetReferenceBusinessObjectName.Count - 1 do
    begin
      ReferenceBusinessObjectName := (BusinessObjectContext.GetConfiguration as ISSBusinessObjectConfiguration).GetReferenceBusinessObjectName.Strings[Index];
      BusinessObjectContext.GetBusinessObjectContainer.AppendObject(ReferenceBusinessObjectName, GetBusinessObject(ReferenceBusinessObjectName).GetObjectInstance);
    end;

  end;

  BusinessObjectContext.SetSystemObject(GetSystemObject);
  BusinessObjectContext.SetConfiguration(BusinessObjectConfiguration);
  ObjectInstance.SetContext(BusinessObjectContext);
  Result := ObjectInstance;
end;

function TSSBusinessObjectFactory.GetBusinessObject(const ABusinessObjectConfiguration: ISSConfiguration): ISSBusinessObject;
var
  BusinessObjectClass: TSSBusinessObjectClass;
  BusinessObjectContext: TSSBusinessObjectContext;
  Index: Integer;
  ObjectInstance: TSSBusinessObject;
  ReferenceBusinessObjectName: string;
  BusinessObjectConfiguration: ISSBusinessObjectConfiguration;
  ScriptLoader: ISSScriptLoader;
  Script: ISSScript;
begin
  BusinessObjectConfiguration := ABusinessObjectConfiguration as ISSBusinessObjectConfiguration;

  //  Init script base Business Object Context
  if BusinessObjectConfiguration.IsBaseScript then
  begin
    ScriptLoader := GetBusinessObject(SS_SCRIPT_LOADER) as ISSScriptLoader;

    try
      Script := ScriptLoader.LoadScript(BusinessObjectConfiguration.GetBusinessObjectName);
    finally
      FreeBusinessObject(ScriptLoader);
    end;

    ObjectInstance := BusinessObjectClass.Create(Self);

    BusinessObjectContext := TSSScriptBusinessObjectContext.Create(nil);
    (BusinessObjectContext as TSSScriptBusinessObjectContext).SetScript(Script);
    (BusinessObjectContext as TSSAdvancedBusinessObjectContext).SetDatabase(((GetSystemObject.GetGlobalObjectTable as ISSObjectContainer).GetObject(SS_DATABASE_CONNECTION_FACTORY_NAME) as ISSDatabaseConnectionFactory).GetDatabaseConnection(BusinessObjectConfiguration.GetDatabaseConnectionName));
    ObjectInstance.SetContext(BusinessObjectContext);
    Result := ObjectInstance;
  end
  else
    //  Init not script base Business Object Context
  begin
    BusinessObjectClass := TSSBusinessObjectClass(QueryClass(BusinessObjectConfiguration.GetBusinessObjectName));
    ObjectInstance := BusinessObjectClass.Create(nil);

    if BusinessObjectConfiguration.IsRequireDatabase then
    begin
      BusinessObjectContext := TSSAdvancedBusinessObjectContext.Create(nil);
      (BusinessObjectContext as TSSAdvancedBusinessObjectContext).SetDatabase(((GetSystemObject.GetGlobalObjectTable as ISSObjectContainer).GetObject(SS_DATABASE_CONNECTION_FACTORY_NAME) as ISSDatabaseConnectionFactory).GetDatabaseConnection(BusinessObjectConfiguration.GetDatabaseConnectionName));
    end
    else
    begin
      BusinessObjectContext := TSSBusinessObjectContext.Create(nil);
    end;

    //  Init Business Object references Business Object
    for Index := 0 to BusinessObjectConfiguration.GetReferenceBusinessObjectName.Count - 1 do
    begin
      ReferenceBusinessObjectName := (BusinessObjectContext.GetConfiguration as ISSBusinessObjectConfiguration).GetReferenceBusinessObjectName.Strings[Index];
      BusinessObjectContext.GetBusinessObjectContainer.AppendObject(ReferenceBusinessObjectName, GetBusinessObject(ReferenceBusinessObjectName).GetObjectInstance);
    end;

    BusinessObjectContext.SetConfiguration(BusinessObjectConfiguration);
    BusinessObjectContext.SetSystemObject(GetSystemObject);
    ObjectInstance.SetContext(BusinessObjectContext);
    Result := ObjectInstance;
  end;

end;

function TSSBusinessObjectFactory.GetBusinessObjectConfiguration(const ABusinessObjectName: string): ISSBusinessObjectConfiguration;
begin
  Result := (GetSystemObject.GetConfigurationTable as ISSConfigurationTable).QueryBusinessObjectConfiguration(ABusinessObjectName) as ISSBusinessObjectConfiguration;
end;

end.
